package alist

import (
	"alist-gui/res"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"sync"
)

type Obj struct {
	mu       sync.Mutex
	runstate bool      // 运行状态
	cmd      *exec.Cmd // cmd
	out      io.Writer // 输出
}

const workDir = "data"
const exeFileName = "alist.exe"

func NewObj(out io.Writer) (*Obj, error) {
	var exePath = filepath.Join(workDir, exeFileName)
	stat, err := os.Stat(exePath)
	if err != nil && os.IsNotExist(err) {
		_ = os.Mkdir(workDir, os.ModePerm)
		fs, err := os.Create(exePath)
		if err != nil {
			return nil, nil
		}
		defer fs.Close()
		_, err = fs.Write(res.AlistRes)
		if err != nil {
			return nil, nil
		}
	} else if err != nil {
		return nil, err
	}

	fmt.Println("new ", stat.Mode())

	return &Obj{
		out: out,
	}, nil
}
func (o *Obj) IsRun() bool {
	return o.runstate
}

func (o *Obj) StartOrStop() error {
	o.mu.Lock()
	defer o.mu.Unlock()
	if o.runstate {
		if err := o.stop(); err != nil {
			return err
		}
		o.runstate = false
		return nil
	}

	if err := o.start(); err != nil {
		return err
	}
	o.runstate = true
	return nil
}

func (o *Obj) start() error {
	cmd := exec.Command("./"+exeFileName, "server")
	cmd.Stdout = o.out
	cmd.Stderr = o.out
	cmd.Dir = workDir
	if err := cmd.Start(); err != nil {
		_, _ = o.out.Write([]byte(err.Error()))
		return err
	}
	o.cmd = cmd
	return nil
}

func (o *Obj) stop() error {
	if err := o.cmd.Process.Kill(); err != nil {
		return err
	}

	return nil
}

func (o *Obj) Canal() {
	if o.cmd != nil {
		o.cmd.Process.Kill()
	}
}
